package com.wzcl.app.service.impl;

import com.wzcl.app.dao.model.Activity;
import com.wzcl.app.dao.model.Commodity;
import com.wzcl.app.dao.model.Material;
import com.wzcl.app.dao.repository.MaterialRepository;
import com.wzcl.app.model.common.BusinessException;
import com.wzcl.app.model.common.CodeMsg;
import com.wzcl.app.model.common.MyPage;
import com.wzcl.app.model.common.WZCL;
import com.wzcl.app.model.dto.MaterialDto;
import com.wzcl.app.service.CommodityService;
import com.wzcl.app.service.MaterialService;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Log4j2
@Service
@Transactional
public class MaterialServiceImpl implements MaterialService {

    @Autowired
    private MaterialRepository repository;

    @Autowired
    private CommodityService commodityService;

    @Override
    public Material addMaterial(MaterialDto materialDto) {
        Material material = new Material();
        BeanUtils.copyProperties(materialDto, material, "id", "state");
        material.setState(WZCL.STATE.NOT_DELETE);
        return repository.save(material);
    }

    @Override
    public Material delMaterialById(Integer id) {
        //校验获取
        Material material = getAndCheckById(id);
        //删除物品的商品
        commodityService.delCommodityByResource(material.getId(), WZCL.COMMODITY_TYPE.MATERIAL);
        //删除
        log.info("Material ID:{} logic deletion", id);
        material.setState(WZCL.STATE.IS_DELETE);
        return repository.save(material);
    }

    @Override
    public void addMaterialCommodity(Commodity commodity) {
        Material material = getAndCheckById(commodity.getResourceId());
        if (material.getCommodity() != null) {
            throw new BusinessException(CodeMsg.SYSTEM_ERR, "该产品已发布商品,无法上线新商品");
        }
        material.setCommodity(commodity);
        repository.save(material);
    }

    @Override
    public void delMaterialCommodityById(Integer id) {
        //校验
        Material material = getAndCheckById(id);
        //解绑
        material.setCommodity(null);
        repository.save(material);
    }

    @Override
    public Material updateMaterial(MaterialDto materialDto) {
        //校验获取
        Material material = getAndCheckById(materialDto);
        //修改
        BeanUtils.copyProperties(materialDto, material, "id", "state");
        return repository.save(material);
    }

    @Override
    public Material getMaterialById(Integer id) {
        return repository.findById(id).orElse(null);
    }

    @Override
    public Material getAndCheckById(Integer id) {
        if (id == null) {
            throw new BusinessException(CodeMsg.MUST_BE_NOT_NULL, "缺少产品Id");
        }
        Material material = getMaterialById(id);
        if (material == null) {
            throw new BusinessException(CodeMsg.MATERIAL_NOT_EXIST);
        }
        if (WZCL.STATE.IS_DELETE.equals(material.getState())) {
            throw new BusinessException(CodeMsg.MATERIAL_IS_DELETE);
        }
        return material;
    }

    @Override
    public List<Material> getMaterialList(MaterialDto materialDto) {
        return repository.findAll(getSpecification(materialDto), materialDto.getSort());
    }

    @Override
    public MyPage<Material> getMaterialPage(MaterialDto materialDto) {
        Page<Material> all = repository.findAll(getSpecification(materialDto), materialDto.getPageable());
        ArrayList<Material> list = new ArrayList<>(all.getContent());
        Collections.reverse(list);
        MyPage<Material> myPage = new MyPage<>();
        myPage.setContent(list);
        myPage.setTotalElements(all.getTotalElements());
        return myPage;
    }

    @Override
    public Material save(Material material) {
        return repository.save(material);
    }


    private Specification<Material> getSpecification(MaterialDto materialDto) {
        return new Specification<Material>() {
            @Override
            public Predicate toPredicate(Root<Material> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<Predicate>();
                if (materialDto.getId() != null) {
                    System.out.println("id不为空");
                    predicates.add(criteriaBuilder.equal(root.get("id"), materialDto.getId()));
                }
                if (!StringUtils.isBlank(materialDto.getName())) {
                    predicates.add(criteriaBuilder.like(root.get("name"), "%" + materialDto.getName() + "%"));
                }
                if (materialDto.getType() != null) {
                    predicates.add(criteriaBuilder.equal(root.get("type"), materialDto.getType()));
                }
                if (materialDto.getIsCommodity() != null) {
                    if (materialDto.getIsCommodity()) {
                        Join<Material, Commodity> commodityPath = root.join("commodity");
                        predicates.add(criteriaBuilder.equal(commodityPath.get("sale"), true));
                    } else {
                        predicates.add(criteriaBuilder.isNull(root.get("commodity")));
                    }
                }
                predicates.add(criteriaBuilder.equal(root.get("state"), WZCL.STATE.NOT_DELETE));
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
    }
}
